package org.hcyspartnoc.luoxin.service.asset.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import jakarta.annotation.Resource;
import org.hcyspartnoc.luoxin.common.core.PageBean;
import org.hcyspartnoc.luoxin.common.core.context.BaseContextHolder;
import org.hcyspartnoc.luoxin.common.core.enums.CoreSysRole;
import org.hcyspartnoc.luoxin.common.enums.user.UserContactTypeEnum;
import org.hcyspartnoc.luoxin.common.exception.asset.AssetVCounselorException;
import org.hcyspartnoc.luoxin.common.exception.common.CommonUtilsException;
import org.hcyspartnoc.luoxin.common.exception.framework.AuthException;
import org.hcyspartnoc.luoxin.mapper.asset.AssetVirtualCounselorMapper;
import org.hcyspartnoc.luoxin.mapper.chat.ChatSessionMapper;
import org.hcyspartnoc.luoxin.mapper.chat.ChatSessionUserMapper;
import org.hcyspartnoc.luoxin.mapper.user.UserContactMapper;
import org.hcyspartnoc.luoxin.pojo.dto.asset.AssetVCounselorAddDto;
import org.hcyspartnoc.luoxin.pojo.dto.asset.AssetVCounselorModifyDto;
import org.hcyspartnoc.luoxin.pojo.po.asset.AssetVirtualCounselorPo;
import org.hcyspartnoc.luoxin.pojo.po.chat.ChatSessionUserPo;
import org.hcyspartnoc.luoxin.pojo.po.system.SysUserPo;
import org.hcyspartnoc.luoxin.pojo.po.user.UserContactPo;
import org.hcyspartnoc.luoxin.pojo.vo.asset.AssetVCounselorAdminVo;
import org.hcyspartnoc.luoxin.pojo.vo.asset.AssetVCounselorVo;
import org.hcyspartnoc.luoxin.service.asset.IAssetVirtualCounselorService;
import org.hcyspartnoc.luoxin.utils.AliyunOssUtils;
import org.hcyspartnoc.luoxin.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
public class AssetVirtualCounselorServiceImpl extends ServiceImpl<AssetVirtualCounselorMapper, AssetVirtualCounselorPo>
        implements IAssetVirtualCounselorService {
    @Resource
    private AssetVirtualCounselorMapper assetVirtualCounselorMapper;
    @Resource
    private AliyunOssUtils aliyunOssUtils;
    @Resource
    private UserContactMapper userContactMapper;
    @Resource
    private ChatSessionMapper chatSessionMapper;
    @Autowired
    private ChatSessionUserMapper chatSessionUserMapper;

    @Override
    @Transactional
    public void addVirtualCounselor(AssetVCounselorAddDto assetVCounselorAddDto) throws CommonUtilsException, AssetVCounselorException {
        // 检查别名是否已经被占用
        if (assetVirtualCounselorMapper.exists(new LambdaQueryWrapper<>(AssetVirtualCounselorPo.class).eq(AssetVirtualCounselorPo::getAlias, assetVCounselorAddDto.getAlias())))
            throw new AssetVCounselorException(AssetVCounselorException.ALIAS_HAS_EXISTS);
        // 验证头像是否存在
        if (!aliyunOssUtils.objectIsExists(assetVCounselorAddDto.getAvatar()))
            throw new CommonUtilsException(CommonUtilsException.SRC_NOT_EXISTS);
        // 将dto转换为po
        AssetVirtualCounselorPo assetVirtualCounselorPo = BeanUtil.copyProperties(assetVCounselorAddDto, AssetVirtualCounselorPo.class);
        // 将style通过“|”分割 重新存储
        String[] styleList = assetVCounselorAddDto.getStyleStringList().split("\\|");
        assetVirtualCounselorPo.setStyle(JSON.toJSONString(styleList));
        // 将openings通过|分割，序列化存储
        String[] openingsList = assetVCounselorAddDto.getOpeningsStringList().split("\\|");
        assetVirtualCounselorPo.setOpenings(JSON.toJSONString(openingsList));
        // 设置创建人为当前用户
        assetVirtualCounselorPo.setCreatedBy(BaseContextHolder.getContext().getBaseCurrentUser().getId());
        // 插入模型
        assetVirtualCounselorPo.setIsOpen(false);
        assetVirtualCounselorMapper.insert(assetVirtualCounselorPo);
    }

    @Override
    @Transactional
    public void modifyVirtualCounselor(AssetVCounselorModifyDto assetVCounselorModifyDto) throws AssetVCounselorException, CommonUtilsException, AuthException {
        // 检查虚拟咨询师是否存在
        AssetVirtualCounselorPo savedVCounselorPo = vCounselorNotExistsThrow(assetVCounselorModifyDto.getId());
        // 校验权限
        authCheck(savedVCounselorPo.getCreatedBy());
        // 检查别名是否已经被占用
        AssetVirtualCounselorPo aliasCounselorPo = assetVirtualCounselorMapper.selectOne(new LambdaQueryWrapper<>(AssetVirtualCounselorPo.class).eq(AssetVirtualCounselorPo::getAlias, assetVCounselorModifyDto.getAlias()));
        if (Objects.nonNull(aliasCounselorPo)) {
            if (!aliasCounselorPo.getId().equals(savedVCounselorPo.getId())) {
                throw new AssetVCounselorException(AssetVCounselorException.ALIAS_HAS_EXISTS);
            }
        }
        // 验证头像是否存在
        if (!aliyunOssUtils.objectIsExists(assetVCounselorModifyDto.getAvatar()))
            throw new CommonUtilsException(CommonUtilsException.SRC_NOT_EXISTS);
        // 将dto转换为po
        AssetVirtualCounselorPo assetVirtualCounselorPo = BeanUtil.copyProperties(assetVCounselorModifyDto, AssetVirtualCounselorPo.class);
        // 将style通过“|”分割 重新存储
        String[] styleList = assetVCounselorModifyDto.getStyleStringList().split("\\|");
        assetVirtualCounselorPo.setStyle(JSON.toJSONString(styleList));
        // 将openings通过|分割，序列化存储
        String[] openingsList = assetVCounselorModifyDto.getOpeningsStringList().split("\\|");
        assetVirtualCounselorPo.setOpenings(JSON.toJSONString(openingsList));
        // 修改该模型关联的会话头像,昵称
        LambdaQueryWrapper<UserContactPo> eq = new LambdaQueryWrapper<UserContactPo>()
                .eq(UserContactPo::getContactId, assetVirtualCounselorPo.getId())
                .eq(UserContactPo::getContactType, UserContactTypeEnum.V_COUNSELOR.getCode());
        List<UserContactPo> userContactPos = userContactMapper.selectList(eq);
        if (Objects.nonNull(userContactPos)&& !userContactPos.isEmpty()) {
            // 修改用户会话信息
            List<Integer> contactIds = userContactPos.stream().map(UserContactPo::getId).toList();
            chatSessionUserMapper.update(new LambdaUpdateWrapper<>(ChatSessionUserPo.class)
                    .in(ChatSessionUserPo::getContactId, contactIds)
                    .set(ChatSessionUserPo::getContactAvatar, assetVCounselorModifyDto.getAvatar())
                    .set(ChatSessionUserPo::getContactName, assetVCounselorModifyDto.getName()));
        }
        // 重新存储
        saveOrUpdate(assetVirtualCounselorPo);
    }

    @Override
    public PageBean<AssetVirtualCounselorPo, AssetVCounselorAdminVo> queryByPage(Integer currentPage, Integer pageSize, String name, String therapy, String styleStringList,Integer isOpen) {
        MPJLambdaWrapper<AssetVirtualCounselorPo> wrapper = new MPJLambdaWrapper<AssetVirtualCounselorPo>()
                .leftJoin(SysUserPo.class, SysUserPo::getId, AssetVirtualCounselorPo::getCreatedBy)
                .selectAll(AssetVirtualCounselorPo.class)
                .selectAs(SysUserPo::getNickname, AssetVirtualCounselorPo::getCreatorNickname)
                .like(AssetVirtualCounselorPo::getName, name)
                .like(AssetVirtualCounselorPo::getTherapy, therapy)
                .eq(isOpen!= 0 ,AssetVirtualCounselorPo::getIsOpen, isOpen == 1);
        for (String style : styleStringList.split("\\|")) {
            wrapper.like(AssetVirtualCounselorPo::getStyle, style);
        }
        // 如果查询用户不是超级管理员，则只能查询到当前用户所创建的
        if (!BaseContextHolder.getContext().getBaseCurrentUser().getRoleId().equals(CoreSysRole.SUPER_ADMIN.getId())) {
            wrapper.eq(AssetVirtualCounselorPo::getCreatedBy, BaseContextHolder.getContext().getBaseCurrentUser().getId());
        }
        Page<AssetVirtualCounselorPo> page = new Page<>(currentPage, pageSize);
        assetVirtualCounselorMapper.selectJoinPage(page, AssetVirtualCounselorPo.class, wrapper);
        ArrayList<AssetVCounselorAdminVo> assetVCounselorAdminVos = new ArrayList<>();
        for (AssetVirtualCounselorPo assetVirtualCounselorPo : page.getRecords()){
            AssetVCounselorAdminVo assetVCounselorAdminVo = BeanUtil.copyProperties(vCounselorToVo(assetVirtualCounselorPo), AssetVCounselorAdminVo.class);
            assetVCounselorAdminVo.setPrompt(assetVirtualCounselorPo.getPrompt());
            assetVCounselorAdminVo.setOpeningList(JSON.parseObject(assetVirtualCounselorPo.getOpenings(), ArrayList.class));
            assetVCounselorAdminVos.add(assetVCounselorAdminVo);
        }
        return new PageBean<>(page, assetVCounselorAdminVos);
    }

    @Override
    @Transactional
    public void removeByVCounselorId(Integer vCounselorId) throws AssetVCounselorException, AuthException {
        AssetVirtualCounselorPo savedVCounselorPo = vCounselorNotExistsThrow(vCounselorId);
        // 校验权限
        authCheck(savedVCounselorPo.getCreatedBy());
        // 删除已经关联的联系人 TODO
        userContactMapper.delete(new LambdaQueryWrapper<>(UserContactPo.class)
                .eq(UserContactPo::getContactId, vCounselorId)
                .eq(UserContactPo::getContactType, UserContactTypeEnum.V_COUNSELOR.getCode()));
        //删除虚拟咨询师
        removeById(vCounselorId);
    }

    @Override
    @Transactional
    public void modifyIsOpen(Integer vCounselorId) throws AssetVCounselorException, AuthException {
        AssetVirtualCounselorPo savedVCounselorPo = vCounselorNotExistsThrow(vCounselorId);
        // 校验权限
        authCheck(savedVCounselorPo.getCreatedBy());
        // 修改状态
        assetVirtualCounselorMapper.update(new LambdaUpdateWrapper<>(AssetVirtualCounselorPo.class).eq(AssetVirtualCounselorPo::getId, vCounselorId)
                .set(AssetVirtualCounselorPo::getIsOpen, !savedVCounselorPo.getIsOpen()));
    }

    @Override
    public PageBean<AssetVirtualCounselorPo, AssetVCounselorVo> queryByToken(Integer currentPage, Integer pageSize) {
        MPJLambdaWrapper<AssetVirtualCounselorPo> wrapper = new MPJLambdaWrapper<AssetVirtualCounselorPo>()
                .leftJoin(UserContactPo.class, UserContactPo::getContactId, AssetVirtualCounselorPo::getId)
                .selectAll(AssetVirtualCounselorPo.class)
                .selectAs(UserContactPo::getContactId, AssetVirtualCounselorPo::getContactId)
                .eq(UserContactPo::getUserId, BaseContextHolder.getContext().getBaseCurrentUser().getId())
                .eq(AssetVirtualCounselorPo::getIsOpen, true);
        Page<AssetVirtualCounselorPo> page = new Page<>(currentPage, pageSize);
        assetVirtualCounselorMapper.selectJoinPage(page, AssetVirtualCounselorPo.class, wrapper);
        ArrayList<AssetVCounselorVo> assetVCounselorVos = new ArrayList<>();
        for (AssetVirtualCounselorPo assetVirtualCounselorPo : page.getRecords())
            assetVCounselorVos.add(vCounselorToVo(assetVirtualCounselorPo));
        return new PageBean<>(page, assetVCounselorVos);
    }

    private void authCheck(Integer idOfCreateBy) throws AuthException {
        // 检查当前用户是否是 创建者 或 超级管理员
        SysUserPo currentUser = BaseContextHolder.getContext().getBaseCurrentUser();
        if (!idOfCreateBy.equals(currentUser.getId()))
            if (!currentUser.getRoleId().equals(CoreSysRole.SUPER_ADMIN.getId()))
                throw new AuthException(AuthException.PERMISSION_NOT_ENOUGH);
    }

    private AssetVCounselorVo vCounselorToVo(AssetVirtualCounselorPo assetVirtualCounselorPo) {
        AssetVCounselorVo assetVCounselorVo = BeanUtil.copyProperties(assetVirtualCounselorPo, AssetVCounselorVo.class);
        assetVCounselorVo.setAvatarUrl(aliyunOssUtils.generateUrl(assetVirtualCounselorPo.getAvatar()));
        assetVCounselorVo.setFormatCreateTime(StringUtils.formatDateTime(assetVCounselorVo.getCreateTime()));
        assetVCounselorVo.setStyleList(JSON.parseObject(assetVirtualCounselorPo.getStyle(), ArrayList.class));
        return assetVCounselorVo;
    }

    private AssetVirtualCounselorPo vCounselorNotExistsThrow(int id) throws AssetVCounselorException {
        AssetVirtualCounselorPo assetVirtualCounselorPo = assetVirtualCounselorMapper.selectOne(new LambdaQueryWrapper<>(AssetVirtualCounselorPo.class).eq(AssetVirtualCounselorPo::getId, id));
        if (Objects.isNull(assetVirtualCounselorPo))
            throw new AssetVCounselorException(AssetVCounselorException.VIRTUAL_COUNSELOR_NOT_EXITS);
        return assetVirtualCounselorPo;
    }
}
